/**
 * 
 */
package com.gragra.sampling.vector;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import com.gragra.sampling.LogarithmicFactorialCash;
import com.gragra.util.OpenUnitElementCounter;
import com.gragra.util.PairNumberer;
/**
 * @author Christoph Teichmann
 * created Apr 29, 2013 8:07:43 PM
 * @version 0.1
 */
public class BinaryStackedClassesUnitCRP extends LimitedClassesUnitCRP
{
	/**
	 * 
	 */
	private final Int2IntOpenHashMap mapToEntry;
	{
		mapToEntry = new Int2IntOpenHashMap();
		mapToEntry.defaultReturnValue(-1);
	}
	/**
	 * 
	 */
	private final PairNumberer units = new PairNumberer();
	/**
	 * 
	 * @param label
	 * @param unit
	 * @return
	 */
	private int getUnit(int label, int unit)
	{return units.get(label, unit);}
	/**
	 * 
	 * @param numberOfLabels
	 * @param unitAlpha
	 * @param labelAlpha
	 * @param threads
	 */
	public BinaryStackedClassesUnitCRP(int numberOfLabels, double[] unitAlpha,
			double labelAlpha, int threads)
	{
		super(numberOfLabels, unitAlpha, labelAlpha, threads);
		int halfLabels = numberOfLabels/2;
		for(int label=0;label<halfLabels;++label)
		{
			for(int unit=0;unit<unitAlpha.length;++unit)
			{
				int un;
				units.put(label, unit,un = this.getFree());
				this.mapToEntry.put(un, unit);
			}
		}
	}
	/* (non-Javadoc)
	 * @see com.gragra.sampling.vector.LimitedClassesUnitCRP#getUnitCash(int)
	 */
	@Override
	protected LogarithmicFactorialCash getUnitCash(int unit)
	{
		int pos = this.mapToEntry.get(unit);
		if(pos >= 0)
		{return this.getCashUnit(pos);}
		return super.getUnitCash(unit);
	}

	/* (non-Javadoc)
	 * @see com.gragra.sampling.vector.LimitedClassesUnitCRP#getElementCash(int, int)
	 */
	@Override
	protected LogarithmicFactorialCash getElementCash(int unit, int element)
	{
		int pos = this.mapToEntry.get(unit);
		if(pos >= 0)
		{return this.getCashElement(pos);}
		return super.getUnitCash(unit);
	}

	/* (non-Javadoc)
	 * @see com.gragra.sampling.vector.LimitedClassesUnitCRP#changeFeatures(com.gragra.sampling.vector.VectorStructure, com.gragra.util.OpenUnitElementCounter, int, int, double)
	 */
	@Override
	protected void changeFeatures(VectorStructure vs,
			OpenUnitElementCounter given,final int label, int thread, double dir)
	{
		int l = label/2;
		double[] values = vs.getValues();
		for(int i=0;i<values.length;++i)
		{
			int un = vs.getCodes()[i][0];
			int el = vs.getCodes()[i][1];
			given.add(this.getUnit(l, un), el, dir*values[i]);
		}
		super.changeFeatures(vs, given, label, thread, dir);
	}
}